package com.luych.userCenter.service;

import com.luych.common.constant.SpringCacheConstant;
import com.luych.common.page.Page;
import com.luych.userCenter.dao.PermissionInfoMapper;
import com.luych.userCenter.dao.RoleRPermissionMapper;
import com.luych.userCenter.dao.UserInfoMapper;
import com.luych.userCenter.dao.UserRRoleMapper;
import com.luych.userCenter.entity.*;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service
public class UserService {

    private final UserInfoMapper userDao;
    private final PasswordEncoder passwordEncoder;
    private final UserRRoleMapper userRRoleDao;
    private final RoleRPermissionMapper roleRPermissionDao;
    private final PermissionInfoMapper permissionInfoDao;

    @Autowired
    public UserService(UserInfoMapper userDao, PasswordEncoder passwordEncoder, UserRRoleMapper userRRoleDao, RoleRPermissionMapper roleRPermissionDao, PermissionInfoMapper permissionInfoDao) {
        this.userDao = userDao;
        this.passwordEncoder = passwordEncoder;
        this.userRRoleDao = userRRoleDao;
        this.roleRPermissionDao = roleRPermissionDao;
        this.permissionInfoDao = permissionInfoDao;
    }

    public UserInfo selectByUserNameAndPassWord(String loginName, String passWord) {
        UserInfoExample example = new UserInfoExample();
        example.or().andLoginNameEqualTo(loginName);
        List<UserInfo> userInfos = userDao.selectByExample(example);
        if (userInfos == null || userInfos.size() == 0) {
            return null;
        }
        UserInfo userInfo = userInfos.get(0);
        if (passwordEncoder.matches(passWord, userInfo.getPassWord())) {
            return userInfo;
        } else {
            return null;
        }
    }

    @Cacheable(cacheNames = SpringCacheConstant.userProvider_userInfo_by_userId, key = "#userId")
    public UserInfo selectUserById(String userId) {
        return userDao.selectByPrimaryKey(userId);
    }

    @Cacheable(cacheNames = SpringCacheConstant.userProvider_userInfo_by_loginName, key = "#loginName")
    public UserInfo selectUserByLoginName(String loginName) {
        UserInfoExample example = new UserInfoExample();
        example.or().andLoginNameEqualTo(loginName);
        List<UserInfo> users = userDao.selectByExample(example);
        return users == null || users.size() == 0 ? null : users.get(0);
    }

    @Caching(
            cacheable = {
                    @Cacheable(cacheNames = SpringCacheConstant.userProvider_userInfo_by_userId, key = "#userInfo.userId"),
                    @Cacheable(cacheNames = SpringCacheConstant.userProvider_userInfo_by_loginName, key = "#userInfo.loginName")
            }
    )
    public UserInfo insert(UserInfo userInfo) {
        userDao.insertSelective(userInfo);
        return userDao.selectByPrimaryKey(userInfo.getUserId());
    }

    @Caching(
            put = {
                    @CachePut(cacheNames = SpringCacheConstant.userProvider_userInfo_by_userId, key = "#userInfo.userId"),
                    @CachePut(cacheNames = SpringCacheConstant.userProvider_userInfo_by_loginName, key = "#userInfo.loginName")
            }
    )
    public UserInfo update(UserInfo userInfo) {
        userDao.updateByPrimaryKeySelective(userInfo);
        return userDao.selectByPrimaryKey(userInfo.getUserId());
    }

    @Caching(
            evict = {
                    @CacheEvict(cacheNames = SpringCacheConstant.userProvider_userInfo_by_userId, key = "#userInfo.userId"),
                    @CacheEvict(cacheNames = SpringCacheConstant.userProvider_userInfo_by_loginName, key = "#userInfo.loginName")
            }
    )
    public void delete(UserInfo userInfo) {
        userDao.deleteByPrimaryKey(userInfo.getUserId());
    }

    public void delete(String userId) {
        delete(selectUserById(userId));
    }

    public Page page(Page page, String keywords) {
        UserInfoExample example = new UserInfoExample();
        if (StringUtils.isNotEmpty(keywords)) {
            example.or().andUserNameLike(keywords);
            example.or().andLoginNameLike(keywords);
        }
        long cnt = userDao.countByExample(example);
        page.setRecordCnt(cnt);
        if (StringUtils.isNotEmpty(page.getSortName()) && StringUtils.isNotEmpty(page.getSortOrder())) {
            example.setOrderByClause(page.getSortName() + " " + page.getSortOrder());
        }
        example.setOffset(page.getPageStart());
        example.setLimit(page.getPageSize());
        List<UserInfo> userInfos = userDao.selectByExample(example);
        page.setRecords(userInfos);
        return page;
    }

    public List<PermissionInfo> permissionsByUser(String userId) {
        UserRRoleExample userRRoleExample = new UserRRoleExample();
        userRRoleExample.or().andUserIdEqualTo(userId);
        List<UserRRole> userRRoles = userRRoleDao.selectByExample(userRRoleExample);
        if (userRRoles == null || userRRoles.size() == 0) return null;
        List<String> roleIds = new ArrayList<>(userRRoles.size());
        for (UserRRole userRRole : userRRoles) {
            roleIds.add(userRRole.getRoleId());
        }
        RoleRPermissionExample roleRPermissionExample = new RoleRPermissionExample();
        roleRPermissionExample.or().andRoleIdIn(roleIds);
        List<RoleRPermission> roleRPermissions = roleRPermissionDao.selectByExample(roleRPermissionExample);
        if (roleRPermissions == null || roleRPermissions.size() == 0) return null;
        List<String> permissionIds = new ArrayList<>(roleRPermissions.size());
        for (RoleRPermission roleRPermission : roleRPermissions) {
            permissionIds.add(roleRPermission.getPermissionId());
        }
        PermissionInfoExample permissionInfoExample = new PermissionInfoExample();
        permissionInfoExample.or().andPermissionIdIn(permissionIds);
        return permissionInfoDao.selectByExample(permissionInfoExample);

    }
}
